﻿using System;

namespace Patterns.ChainOfResponsibility {

    public class AbstractExample {

        public static void Run() {
            // Setup Chain of Responsibility
            Handler h1 = new ConcreteHandler1();
            Handler h2 = new ConcreteHandler2();
            Handler h3 = new ConcreteHandler3();
            h1.SetSuccessor(h2);
            h2.SetSuccessor(h3);

            // Generate and process request
            int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };

            Array.ForEach(requests, request =>
                h1.HandleRequest(request));
        }

        // "Handler"
        private abstract class Handler {
            protected Handler successor;

            public void SetSuccessor(Handler successor) {
                this.successor = successor;
            }

            public abstract void HandleRequest(int request);
        }

        // "ConcreteHandler1"
        private class ConcreteHandler1 : Handler {
            public override void HandleRequest(int request) {
                if (request >= 0 && request < 10)
                    Console.WriteLine("{0} handled request {1}",
                      this.GetType().Name, request);
                else if (successor != null)
                    successor.HandleRequest(request);
            }
        }

        // "ConcreteHandler2"
        private class ConcreteHandler2 : Handler {
            public override void HandleRequest(int request) {
                if (request >= 10 && request < 20)
                    Console.WriteLine("{0} handled request {1}",
                      this.GetType().Name, request);
                else if (successor != null)
                    successor.HandleRequest(request);
            }
        }

        // "ConcreteHandler3"
        private class ConcreteHandler3 : Handler {
            public override void HandleRequest(int request) {
                if (request >= 20 && request < 30)
                    Console.WriteLine("{0} handled request {1}",
                      this.GetType().Name, request);
                else if (successor != null)
                    successor.HandleRequest(request);
            }
        }
    }
}
